package com.tianji.promotion.service.impl;


import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.ObjectUtils;
import com.tianji.common.utils.StringUtils;
import com.tianji.promotion.domain.dto.CouponFormDTO;
import com.tianji.promotion.domain.dto.CouponIssueFormDTO;
import com.tianji.promotion.domain.po.Coupon;
import com.tianji.promotion.domain.po.CouponScope;
import com.tianji.promotion.domain.vo.CouponPageVO;
import com.tianji.promotion.enums.CouponStatus;
import com.tianji.promotion.mapper.CouponMapper;
import com.tianji.promotion.query.CouponQuery;
import com.tianji.promotion.service.ICouponScopeService;
import com.tianji.promotion.service.ICouponService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.tianji.promotion.service.IExchangeCodeService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

import static com.tianji.promotion.enums.CouponStatus.*;
import static com.tianji.promotion.enums.ObtainType.ISSUE;

/**
 * <p>
 * 优惠券的规则信息 服务实现类
 * </p>
 *
 * @author wangyuqing
 * @since 2024-09-01
 */
@Service
@RequiredArgsConstructor
public class CouponServiceImpl extends ServiceImpl<CouponMapper, Coupon> implements ICouponService {
    private final ICouponScopeService couponScopeService;
    private final IExchangeCodeService codeService;

    /**
     * 1.新增优惠券
     *
     * @param dto 优惠券信息dto
     */
    @Override
    public void saveCoupon(CouponFormDTO dto) {
        //1.dto转换为po
        Coupon coupon = BeanUtils.copyBean(dto, Coupon.class);
        //2.新增优惠券到数据库
        save(coupon);
        //3.转存优惠券适用范围的中间表
        //3.优惠券是否是特定范围，不是，直接返回
        if (!dto.getSpecific()) {
            return;
        }
        //3.1获取优惠券使用范围，判断优惠券适用范围是否为空，如果为空，抛出异常
        List<Long> scopes = dto.getScopes();
        if (scopes == null || scopes.isEmpty()) {
            throw new BizIllegalException("优惠券使用范围不能为空");
        }
        //3.2获取优惠券ID
        Long couponId = coupon.getId();
        //3.3存入中间表（优惠券Id，作用范围Id）
        List<CouponScope> list = scopes.stream().map(scopeId -> new CouponScope().setCouponId(couponId)
                .setBizId(scopeId)).collect(Collectors.toList());
        couponScopeService.saveBatch(list);
    }


    /**
     * 2.分页查询优惠券
     *
     * @param query 分页查询参数
     */
    @Override
    public PageDTO<CouponPageVO> pageQueryCoupon(CouponQuery query) {
        //1.根据条件分页查询优惠券
        Page<Coupon> page = lambdaQuery().eq(query.getStatus() != null, Coupon::getStatus, query.getStatus())
                .eq(query.getType() != null, Coupon::getType, query.getType())
                .like(StringUtils.isNotBlank(query.getName()), Coupon::getName, query.getName())
                .page(query.toMpPageDefaultSortByCreateTimeDesc());
        //2.处理VO
        List<Coupon> records = page.getRecords();
        //如果数据为空，直接返回
        if (BeanUtils.isEmpty(records)) {
            return PageDTO.empty(page);
        }
        List<CouponPageVO> couponPageVO = BeanUtils.copyList(records, CouponPageVO.class);
        //3.返回
        return PageDTO.of(page, couponPageVO);
    }

    /**
     * 3.发放优惠券
     *
     * @param dto 发放优惠券的参数
     */
    @Override
    @Transactional
    public void beginIssue(CouponIssueFormDTO dto) {
        //1.校验优惠券是否存在
        Coupon coupon = getById(dto.getId());
        if (ObjectUtils.isEmpty(coupon)) {
            throw new BizIllegalException("优惠券不存在");
        }
        //2.判断优惠券状态是否是暂停或者未发放，如果是，抛出异常
        if (coupon.getStatus() != CouponStatus.PAUSE && coupon.getStatus() != DRAFT) {
            throw new BizIllegalException("优惠券状态不正确");
        }
        //3.判断优惠券是否是立马发放
        LocalDateTime issueBeginTime = dto.getIssueBeginTime();
        LocalDateTime now = LocalDateTime.now();
        boolean isBegin = (!issueBeginTime.isAfter(now) || issueBeginTime == null);
        //4.更新优惠券状态
        Coupon coupon1 = BeanUtils.copyBean(dto, Coupon.class);
        if (isBegin) {
            coupon.setStatus(ISSUING);
            coupon.setIssueBeginTime(now);
        } else {
            coupon.setStatus(UN_ISSUE);
        }
        updateById(coupon1);
        //5.生成兑换码
        //5.1、满足优惠券获取方式是兑换码，并且优惠券状态是未发放，则生成兑换码
        if (coupon.getObtainWay() == ISSUE && coupon.getStatus() == DRAFT) {
            //5.2准备参数，兑换码的有效时间就是优惠券的过期时间
            coupon.setIssueEndTime(coupon1.getIssueEndTime());
            //5,3 生成兑换码
            codeService.asyncGenerateCode(coupon);
        }
    }
}
